#pragma once

#include <iostream>
#include <unordered_map>
#include <memory>
#include "Connection.hpp"
#include "Epoller.hpp"

class Reactor
{
    static const int _Esize = 128;

private:
    bool Exist(std::shared_ptr<Connection> &_connect)
    {
        auto _it = _connections.find(_connect->Sockfd());
        return _it != _connections.end();
    }

public:
    Reactor()
    {
    }

    void AddConnection(std::shared_ptr<Connection> &_connect)
    {
        if (Exist(_connect))
        {
            return;
        }
        _connect->SetOwner(this);

        _connections.insert({_connect->Sockfd(), _connect});
        _epoller.AddEvents(_connect->Sockfd(), _connect->GetEvents());
    }

    void Dispatcher()
    {
        while (1)
        {
            int timeout = 1000;
            int n = _epoller.Wait(_revs, timeout, _Esize);
            for (int i = 0; i < n; i++)
            {
                if (_revs[i].events & EPOLLIN)
                {
                    int _sockfd = _revs[i].data.fd;
                    _connections[_sockfd]->Recv();
                }

                if (_revs[i].events & EPOLLOUT)
                {
                    int _sockfd = _revs[i].data.fd;
                    _connections[_sockfd]->Send();
                }
            }
        }
    }

    ~Reactor()
    {
    }

private:
    std::unordered_map<int, std::shared_ptr<Connection>> _connections;
    Epoller _epoller;
    struct epoll_event _revs[_Esize];
};
